/*
 * Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package top.continew.admin.asset.service.impl;

import cn.crane4j.core.util.CollectionUtils;
import cn.crane4j.core.util.StringUtils;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;

import org.apache.commons.collections4.ListUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Service;

import org.springframework.transaction.annotation.Transactional;
import top.continew.admin.asset.mapper.*;
import top.continew.admin.asset.model.entity.*;
import top.continew.starter.core.exception.BusinessException;
import top.continew.starter.extension.crud.model.query.PageQuery;
import top.continew.starter.extension.crud.model.resp.PageResp;
import top.continew.starter.extension.crud.service.BaseServiceImpl;
import top.continew.admin.asset.model.query.CheckTaskQuery;
import top.continew.admin.asset.model.req.CheckTaskReq;
import top.continew.admin.asset.model.resp.CheckTaskDetailResp;
import top.continew.admin.asset.model.resp.CheckTaskResp;
import top.continew.admin.asset.service.CheckTaskService;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 盘点任务业务实现
 *
 * @author CharlieYan
 * @since 2025/07/11 15:07
 */
@Service
@RequiredArgsConstructor
public class CheckTaskServiceImpl extends BaseServiceImpl<CheckTaskMapper, CheckTaskDO, CheckTaskResp, CheckTaskDetailResp, CheckTaskQuery, CheckTaskReq> implements CheckTaskService {

    private final CheckItemMapper checkItemMapper;
    private final DeviceRecordsMapper deviceRecordsMapper;
    private final PartRecordsMapper partRecordsMapper;
    private final SoftwareRecordsMapper softwareRecordsMapper;

    @Override
    public Integer updateCheckTaskStatus(@Param("taskId") Long taskId, @Param("status") Integer status) {
        return baseMapper.updateCheckTaskStatus(taskId, status);
    }

    @Override
    public CheckTaskDetailResp get(Long id) {
        return baseMapper.selectCheckTaskById(id);
    }

    @Override
    public PageResp<CheckTaskResp> page(CheckTaskQuery query, PageQuery pageQuery) {
        QueryWrapper<CheckTaskDO> queryWrapper = this.buildQueryWrapper(query);
        super.sort(queryWrapper, pageQuery);
        IPage<CheckTaskDetailResp> page = baseMapper.selectCheckTasksPage(new Page<>(pageQuery.getPage(), pageQuery
            .getSize()), queryWrapper);
        PageResp<CheckTaskResp> pageResp = PageResp.build(page, super.getListClass());
        pageResp.getList().forEach(this::fill);
        return pageResp;
    }

    @Override
    protected QueryWrapper<CheckTaskDO> buildQueryWrapper(CheckTaskQuery query) {
        String fuzzy = query.getFuzzy();
        return new QueryWrapper<CheckTaskDO>().and(StrUtil.isNotBlank(fuzzy), q -> q.like("tt.name", fuzzy)
            .or()
            .like("tt.nickname", fuzzy));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long create(CheckTaskReq req) {
        // 1. 创建盘点任务
        Long taskId = super.create(req);

        // 2. 根据类型处理不同资产
        String type = req.getType();
        if (StringUtils.isBlank(type)) {
            throw new BusinessException("盘点类型不能为空");
        }

        // 3. 批量插入处理
        if (type.equals("0")) {
            batchInsertCheckItems(getDeviceItems(taskId));
        } else if (type.equals("1")) {
            batchInsertCheckItems(getPartItems(taskId));
        } else if (type.equals("2")) {
            batchInsertCheckItems(getSoftwareItems(taskId));

        } else {
            log.warn("未知的盘点类型: {" + type + "}");
            throw new BusinessException("不支持的盘点类型: " + type);
        }
        return taskId;
    }

    // 批量插入检查项（带分页处理）
    private void batchInsertCheckItems(List<CheckItemDO> items) {
        if (CollectionUtils.isEmpty(items)) {
            log.warn("没有需要插入的盘点项");
            return;
        }

        int batchSize = 500; // 每批插入500条
        List<List<CheckItemDO>> batches = ListUtils.partition(items, batchSize);

        batches.forEach(batch -> {
            try {
                checkItemMapper.insertBatch(batch);
            } catch (DataAccessException e) {
                log.error("批量插入盘点项失败", e);
                throw new BusinessException("创建盘点明细失败", e);
            }
        });
    }

    // 获取设备盘点项
    private List<CheckItemDO> getDeviceItems(Long taskId) {
        // 查询未删除的设备记录 (0表示未删除)
        List<DeviceRecordsDO> devices = deviceRecordsMapper.selectList(new LambdaQueryWrapper<DeviceRecordsDO>()
            .eq(DeviceRecordsDO::getIsDel, 0) // 修正为0=未删除
        );

        return devices.stream()
            .map(device -> createCheckItem(taskId, device.getId(), device.getCode(), device.getName(), device.getSn()))
            .collect(Collectors.toList());
    }

    // 获取配件盘点项
    private List<CheckItemDO> getPartItems(Long taskId) {
        // 查询未删除的设备记录 (0表示未删除)
        List<PartRecordsDO> parts = partRecordsMapper.selectList(new LambdaQueryWrapper<PartRecordsDO>()
            .eq(PartRecordsDO::getIsDel, 0) // 有效配件
        );

        return parts.stream()
            .map(part -> createCheckItem(taskId, part.getId(), part.getCode(), part.getName(), part.getSn()))
            .collect(Collectors.toList());
    }

    // 获取软件盘点项
    private List<CheckItemDO> getSoftwareItems(Long taskId) {
        // 实际实现应根据业务需求
        List<SoftwareRecordsDO> softwareList = softwareRecordsMapper
            .selectList(new LambdaQueryWrapper<SoftwareRecordsDO>().eq(SoftwareRecordsDO::getIsDel, 0) //有效软件
            );

        return softwareList.stream()
            .map(software -> createCheckItem(taskId, software.getId(), software.getCode(), software.getName(), software
                .getSn()))
            .collect(Collectors.toList());
    }

    // 创建检查项对象
    private CheckItemDO createCheckItem(Long taskId, Long itemId, String code, String name, String sn) {
        CheckItemDO item = new CheckItemDO();
        item.setTaskId(taskId);
        item.setItemId(itemId);
        item.setCode(code);
        item.setName(name);
        item.setSn(sn);
        item.setStatus(0); // "待盘点"
        return item;
    }

}